package com.huitone.smspfm.core.filter;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.Set;

import javax.security.auth.login.AppConfigurationEntry;

import com.huitone.smspfm.logger.ExtLogger;
import com.bin.common.utils.StringUtils;
import com.huitone.smspfm.core.config.AppStaticConfigs;
import com.huitone.smspfm.core.constant.DealResult;
import com.huitone.smspfm.core.waterpipe.client.impl.SimpleGateLink;
import com.huitone.smspfm.dao.oracle.entity.GateDef.SignType;
import com.huitone.smspfm.model.SmsEntityForMt;
import com.huitone.smspfm.task.GetPriListLengthTask;

/**   
* @Title SmsRouteFilterTask.java 
* @Package com.huitone.smspfm.core.task 
* @Description TODO(用一句话描述该文件做什么) 
* @author ybliang   
* @date 2017年6月18日 上午10:54:49 
* @version V1.0   
*/
public class SmsRouteFilterTask extends Thread {
	
	private ExtLogger logger = ExtLogger.create(SmsRouteFilterTask.class);
	
	private String moduleName = "短信路由模块";
	
	//private byte[] moduleNameB = AppStaticConfigs.stringRedisSerializer.serialize(moduleName); 
	
	private List<SmsEntityForMt> entities = null;

	private boolean smsSign = true;
	
	private CyclicBarrier barrier = null;
	
	public SmsRouteFilterTask(List<SmsEntityForMt> entities, CyclicBarrier barrier) {
		this.entities = entities;
		this.barrier = barrier;
	}

	public SmsRouteFilterTask(List<SmsEntityForMt> entities, CyclicBarrier barrier,boolean smsSign) {
		this(entities,barrier);
		this.smsSign = smsSign;
	}

	@Override
	public void run() {
		
		if (entities == null) return;
		
		long start = System.currentTimeMillis();
		
		for (int i = 0 ; i < entities.size() ; i ++) {
			
			SmsEntityForMt entity = entities.get(i);
			
			String srvNode = StringUtils.toString(entity.getSrvNode());
			String serviceCode = StringUtils.toString(entity.getServiceCode());
			
			String linkId = null;
			String priListName = findABestPriList(entity);
			
			if (!StringUtils.isEmpty(priListName)) {
				linkId = StringUtils.splitThRIndex(priListName, ":", 1);
			}
			
					
			SimpleGateLink iGateLink = null;
			if(! StringUtils.isEmpty(linkId)){
				iGateLink = (SimpleGateLink) AppStaticConfigs.simpleGateLinkRegister.get(linkId);
			}
			
			
			if (iGateLink != null && !StringUtils.isEmpty(priListName) ) {
				
				/**
				 * 附加签名动作开始
				 */
				if (this.smsSign) {
					String signType = iGateLink.getGateDef().getSignType();

					if (!StringUtils.equals(SignType.zero.value(), signType)) {

						String sgcontent = AppStaticConfigs.configSnodeScodeSignMap.get(srvNode + ":" + serviceCode);

						if (StringUtils.isEmpty(sgcontent)) {
							sgcontent = AppStaticConfigs.configSnodeScodeSignMap.get(srvNode + ":");
						}

						if (StringUtils.isEmpty(sgcontent)) {
							sgcontent = AppStaticConfigs.configSnodeScodeSignMap.get(":" + serviceCode);
						}

						if (StringUtils.isEmpty(sgcontent)) {
							sgcontent = AppStaticConfigs.configSnodeScodeSignMap.get(":");
						}

						if (StringUtils.equals(SignType.one.value(), signType)) { // 在短信正文前面附加签名
							entity.setContent(StringUtils.toString(sgcontent) + entity.getContent());
						} else if (StringUtils.equals(SignType.two.value(), signType)) { // 在短信正文后面附加签名
							entity.setContent(entity.getContent() + StringUtils.toString(sgcontent));
						}

					}

					/**
					 * 附加签名动作结束
					 */
				}
				
				entity.setDealResultCodeMap(moduleName, DealResult.RESULT0);
				entity.setGateLinkId(linkId);
				entity.setPriListName(priListName);
				
				//GetPriListLengthTask.priListLength.put(priListName, GetPriListLengthTask.priListLength.get(priListName) + 1);
				
				logger.debug("[序列号:用户号码][" + entity.getSerialno() + ":" + entity.getPhoneNumber() + "]路由到优先级队列：" + priListName);
				
			} else {
				
				entity.setDealResultCodeMap(moduleName, DealResult.RESULT_9);
				
				logger.debug("[序列号:用户号码][" + entity.getSerialno() + ":" + entity.getPhoneNumber() + "]路由失败。");
			}
		}
		
		long end = System.currentTimeMillis();
		
		logger.debug("短信路由执行完毕,共耗时:" + (end - start) + "毫秒");
		
		try {
			barrier.await();
		} catch (InterruptedException | BrokenBarrierException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 找到最优的队列(当前待发送短信最少的队列)
	 * @param entity
	 * @return
	 */
	public String findABestPriList(SmsEntityForMt entity) {
		
		String result = null;
		
		String srvNode = StringUtils.toString(entity.getSrvNode());
		String serviceCode = StringUtils.toString(entity.getServiceCode());
		
		Integer level = AppStaticConfigs.configSnodeScodePLvMap.get(srvNode + ":" + serviceCode);
		
		Set<String> set = findABestGateLink2(entity);
		
		if(set == null || set.size() == 0 ){
			//未能成功匹配到路由失败
			return result;
		}
		
		if (level != null && level == 0) { // 当优先级为0时找出最短的队列
			
			Long tmpLength = -1L;
			int routeLevel = -1;
			//gtLinkIds  [gtLinkId:routeLevel]
			for (String gtLinkIds:set) {
				String gtLinkId = StringUtils.splitThRIndex(gtLinkIds, ":", 0);		
				int rlevel = 	StringUtils.toInteger(StringUtils.splitThRIndex(gtLinkIds, ":", 1));
				if(rlevel == 0){
					rlevel = 999;
				}
				if(routeLevel == -1){
					routeLevel = rlevel;
				}
				
				if(rlevel > routeLevel){
					continue;
				}
				
//				String priListName = "SM:" + gtLinkId + ":Pri:0:List";
				String priListName = "SM:" + gtLinkId + ":Cache:0:List";
				Long length = GetPriListLengthTask.priListLength.get(priListName);
				if (length == null) {
					length = 0L;
				}
				
				if (tmpLength == -1L) {
					tmpLength = length;
					result = priListName;
				} else {
					if (length < tmpLength) {
						tmpLength = length;
						result = priListName;
					}
				}
			}
			
		} else { // 当优先级不为0时找出对应网关所有优先级队列长度之和最小的优先级队列
			
			if (level == null) {
				level = AppStaticConfigs.configMinPLvInteger;
			}
			
			if (level == null) {
				return null;
			}
			
			Long tmpLength = -1L;
			int routeLevel = -1;
			for (String gtLinkIds:set) {
				String gtLinkId = StringUtils.splitThRIndex(gtLinkIds, ":", 0);		
				int rlevel = 	StringUtils.toInteger(StringUtils.splitThRIndex(gtLinkIds, ":", 1));
//				String priListName = "SM:" + gtLinkId + ":Pri:" + level + ":List";
				String priListName = "SM:" + gtLinkId + ":Cache:" + level + ":List";
				if(rlevel == 0){
					rlevel = 999;
				}
				
				if(routeLevel == -1){
					routeLevel = rlevel;
				}
				
				if(rlevel > routeLevel){
					continue;
				}
				Long length = 0L;
				Iterator<Entry<String, Long>> iterator = GetPriListLengthTask.priListLength.entrySet().iterator();
				while(iterator.hasNext()) {
					Entry<String, Long> entry = iterator.next();
//					if (StringUtils.startsWith(entry.getKey(), "SM:" + gtLinkId + ":Pri:")) {
					if (StringUtils.startsWith(entry.getKey(), "SM:" + gtLinkId + ":Cache:")) {
						length += entry.getValue();
					}
				}
				
				if (tmpLength == -1L) {
					tmpLength = length;
					result = priListName;
				} else {
					if (length < tmpLength) {
						tmpLength = length;
						result = priListName;
					}
				}
			}
		}
		
		return result;
	}
	
	/**
	 * 查找可用的网关通道ID
	 * 查找逻辑:
	 * 1 业务路由:根据短信业务查询是否有可用的网关通道,如果没有则匹配到业务则查找全局的业务路由(业务字段为空的记录)
	 * 2 号段路由:根据号段匹配到该号段所属运营商以及所属省份
	 * 3 综合路由:根据可发送运营商及省份找到实际可发送网关通道
	 * @param entity
	 * @return 当前业务可用通道（包括虚通道）
	 */
	public Set<String> findABestGateLink2(SmsEntityForMt entity) {
		
		String serviceCode = StringUtils.toString(entity.getServiceCode());
		
		Set<String> usableGateLinkIds = new HashSet<>();
		
		Set<String> faultGateLinkIds = new HashSet<>();
		
		Set<String> gateLinkIds = new HashSet<>();
		
		Set<String> gliset1 = AppStaticConfigs.configScodeGtLinkIdMap.get(serviceCode);
		
		Set<String> gliset2 = AppStaticConfigs.configScodeGtLinkIdMap.get("*");
		
		if (gliset1 != null && !gliset1.isEmpty()) {
			gateLinkIds.addAll(gliset1);
		} else {
			if (gliset2 != null && !gliset2.isEmpty()) {
				gateLinkIds.addAll(gliset2);
			}
		}
		
		// 查找出有效的gateLinkId(通道可发送省份表及通道可发送运营商表同时查找到)
		if (!gateLinkIds.isEmpty()) {
			
			String userNumber = StringUtils.toString(entity.getPhoneNumber());
			
			int length = userNumber.length() - 4;
			
			for (int i = length ; i > 2 ; i --) {
				//手机号段路由
				String tmpUN = StringUtils.substring(userNumber, 0, i);
				String[] strings = AppStaticConfigs.configUserRouteMap.get(tmpUN);
				if (strings != null) {
					
					String probelong = strings[0];
					String corpbelong = strings[1];
					
					if (!StringUtils.isEmpty(probelong) && !StringUtils.isEmpty(corpbelong)) {
						//业务类型路由
						for (String id:gateLinkIds) {
							String gateLiskId = id.substring(0,id.indexOf(":"));
//							String level = id.substring(id.indexOf(":")+1);
							Set<String> set1 = AppStaticConfigs.configProvGtLinkIdMap.get(probelong);
							Set<String> set2 = AppStaticConfigs.configCorpGtLinkIdMap.get(corpbelong);
							
							if (set1 != null && set1.contains(gateLiskId) && set2 != null && set2.contains(gateLiskId)) {
								//检测通道是否故障
								if(checkRouteFaultStatus(id)){
									usableGateLinkIds.add(id);
								} else {
									faultGateLinkIds.add(id);
								}
								
							}
						}
						
						break;
					}
				} else {
					continue;
				}
			}
		}
		
		if(usableGateLinkIds.size() == 0){
			Set<String> tempSet = new HashSet<String>();
			//查询虚通道
			if(faultGateLinkIds.size() > 0){
				for(String id: faultGateLinkIds){
					Set<String> virtualIds = AppStaticConfigs.virtualGateLinkIdMap.get(id);
					for(String virtualId: virtualIds){
						String linkId = StringUtils.splitThRIndex(virtualId, ":", 0);					
						if(checkRouteFaultStatus(linkId)){
							tempSet.add(linkId);
						}
					}
				}
			}
			if(tempSet.size() > 0){
				usableGateLinkIds = tempSet;
			}
		}
		
		return usableGateLinkIds;
	}
	
	public String getMinSizeZeroListName(Set<String> gateLinkIds, Set<String> levels) {
		
		String gateLinkId = "";
		
		if (levels != null && levels.contains("0") && gateLinkIds != null) {
			
			long tmp = 0;
			
			for (String linkId:gateLinkIds) {
				
//				String tmpName = "SM:" + linkId + ":Pri:0:List";
				String tmpName = "SM:" + linkId + ":Cache:0:List";
				
				long length = AppStaticConfigs.listOpts.length(tmpName);
				if (length > tmp) {
					tmp = length;
					gateLinkId = linkId;
				}
			}
		}
		
		return gateLinkId;
	}
	
	public String[] getMinSizeListName(Set<String> gateLinkIds, Set<String> levels) {
		
		String[] result = new String[2];
		
		Set<Integer> ldefs = AppStaticConfigs.configAllPLv;
		
		String gateLinkId = "";
		
		Long minSize = null;
		
		if (gateLinkIds != null) {
			
			for (String gld:gateLinkIds) {
				
				long tmpSize = 0;
				
				for (Integer ldef:ldefs) {
//					tmpSize += AppStaticConfigs.listOpts.length("SM:" + gld + ":Pri:" + ldef + ":List");
					tmpSize += AppStaticConfigs.listOpts.length("SM:" + gld + ":Cache:" + ldef + ":List");
				}
				
				if (minSize == null) {
					minSize = tmpSize;
					gateLinkId = gld;
				} else if (tmpSize < minSize) {
					minSize = tmpSize;
					gateLinkId = gld;
				}
			}
			
			if (!StringUtils.isEmpty(gateLinkId)) {
				
				if (levels != null && !levels.isEmpty()) {
					for (String level:levels) {
						result[0] = gateLinkId;
						result[1] = level;
						break;
					}
				}
				
				if (StringUtils.isEmpty(result[0]) || StringUtils.isEmpty(result[1])) {
					result[0] = gateLinkId;
					result[1] = AppStaticConfigs.configMinPLvInteger + "";
				}
			}
		}
		
		return result;
	}
	
	private boolean checkRouteFaultStatus(String linkId){
		SimpleGateLink tempGateLink = (SimpleGateLink) AppStaticConfigs.simpleGateLinkRegister.get(linkId);
		return (tempGateLink == null || ! StringUtils.equals("1", tempGateLink.getGateDef().getFaultStatus()));
	}
}
